import { formatDate } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { AfterViewInit, Component, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { NzOptionComponent } from 'ng-zorro-antd/select';
import { lastValueFrom, map, Observable, of, Subject } from 'rxjs';
import { DyformCommonService } from './services/dyform-common.service';
import { afterSetFormData } from './libs/after-set-form-data';
import { beforSubmit } from './libs/before-submit';
import { dataFormat } from './libs/data-format';
import { getLeafData } from './libs/utils';
import { UserInfoData, UserInfoService } from 'src/app/service/user-info/user-info.service';
import { NzMessageService } from 'ng-zorro-antd/message';
import 报装申请 from './../../../assets/json/报装申请'
import { NzModalService } from 'ng-zorro-antd/modal';
import { MessageService } from 'src/app/service/message.service';
import { CommonService } from 'src/app/service/common/common.service';
import { DY_FORM_LINK } from 'src/app/utils/dy-form-link';

@Component({
  selector: 'app-dynamic-form',
  templateUrl: './dynamic-form.component.html',
  styleUrls: ['./dynamic-form.component.scss']
})
export class DynamicFormComponent implements OnInit {
  
  redirect_url = '' // 返回和提交成功跳转地址
  pageType = '' // 0-新增 1-更新 2-删除
  isSingleRow = false

  dyForm = null // 获取的动态表单配置文件
  dyFormData = null // 动态表单数据 | 更新和删除时有
  groupList: any = [] // 字段集合

  isDetail = 'true'
  setId = ''
  typeId = ''
  isRealName = '0' // 是否实名认证
  name = '' // 表单标题
  sortName = '' // 功能所属分类

  usageCode = ''
  usageCodeDisabled = false
  bindType = ''

  // 实名认证
  authCode = ''
  constructor(
    private http: HttpClient,
    // private util: CommonUtilService,
    // private bankTransferService: BankTransferService,
    private route: ActivatedRoute,
    private dyFormService: DyformCommonService,
    private router: Router,
    private userInfoService: UserInfoService,
    private message: MessageService,
    public common: CommonService
  ) { }
 
  _initDefaultValue(){
    this.groupList.forEach((group: any) => {
      const groupData = group.groupData
      console.log(this.validateForm)
      groupData.forEach((item: any) => {
        if(item.fieldType === 'userHelp'){
        }
        if(item.fieldType === 'bank'){
          if(item.defaultValue){
            const defaultValue = JSON.parse(item.defaultValue)
            this._setValue('account', defaultValue.account)
            this._setValue('bankId', defaultValue.bankName)
          }
        }
        if(item.fieldType === 'reactSelect'){
          if(item.defaultValue){
            this._setValue(item.fieldKey, item.defaultValue.split(','))
            return
          }
        }
        // switch
        if(item.fieldType === 'switch'){
          if(item.defaultValue === 'true'){
            this._setValue(item.fieldKey, true)
            return
          }
          this._setValue(item.fieldKey, false)
          return
        }
        // 文本框 用户编号 特殊处理(给默认值)
        if(item.fieldKey === 'usageCode' && this.usageCode){
          this._setValue('usageCode', this.usageCode)
          return
        }

        this._setValue(item.fieldKey, this._getDefaultValue(item.defaultValue))
        
      })
    })

    this._setFormDataWhenUpdAndDel()
  }

  _setFormDataWhenUpdAndDel(){
    this.pageType = this.dyFormService.pageType
    this.dyFormData = this.dyFormService.formData
    
    if(this.isDetail === 'false'){
      this.disableForm()
      this.submitBtnVisible = false
    }

    // 更新或者删除
    if(this.pageType === '1' || this.pageType === '2'){
      const formData: any = this.dyFormService.formData
      Object.keys(formData).forEach(key => {
        this._setValue(key, formData[key])
      })
    }
    // 删除
    if(this.pageType === '2'){
      this.disableForm()
    }

    this.dyFormService.pageType = ''
    this.dyFormService.formData = null

    // 特殊值处理
    afterSetFormData(this)
    console.log(this.groupList)
  }

  validateForm: FormGroup = new FormGroup({
    isSecret: new FormControl(true),
    infoSources: new FormControl('WT'),
    msgWay: new FormControl('0dc1cc45-7a35-4241-888c-9f392a5e2f17')
  })

  userInfo: any = {} as UserInfoData 
  ngOnInit() { 
    this.route.queryParams.subscribe((res: any) => {
      this.typeId = res.id
      this.isDetail = res.isDetail
      this.name = res.name
      this.sortName = res.sortName
      this.usageCode = res.usageCode
      this.bindType = res.bindType
      this.authCode = res.authCode
      this.redirect_url = res.path ? res.path : '/home'
      
      if(!this.userInfoService.getIsLogin()){
        this.message.info('当前页面需要登录才可继续操作,请先登录')
        console.log(location)
        this.router.navigate(['/login'], { queryParams: { redirect_url: 'base-form', ...res } })
        return
      }
      this.userInfo = this.userInfoService.getUserInfo() as UserInfoData

      // 初始化页面
      this.initPage()
      // 获取字段
      this.getField()
    })
  }

  getField(){
    this._getField(this.typeId, this.isDetail).subscribe(res => {
      this.dyForm = res
      this.groupList = res.groupList
      this.setId = res.setId
      this.isRealName = res.isRealName

      // 获取申请须知
      this._getIfApplyOrSign(this.groupList)

      // 初始化表单
      this.initForm()

      // 设置默认值
      // TODO 小心此处 setTimeout 的坑
      setTimeout(() => {
        this._initDefaultValue()
      }, 0);
    })
  }
  initPage(){
  }

  initForm(){
    this.groupList.forEach((group: any) => {
      const groupData = group.groupData
      groupData.forEach(async (item: any) => {

        if(item.fieldKey === 'applyAgree'){
          return
        }

        if(item.fieldType === 'bank'){
          this.validateForm.addControl('account', new FormControl('', this.setValidators(item)))
          this.validateForm.addControl('bankId', new FormControl('', this.setValidators(item)))
        }
        if(item.fieldType === 'userHelp'){
          this.validateForm.addControl('bindType', new FormControl(this.bindType, []))
          // this.validateForm.addControl('usageCode', new FormControl('', []))
          // this.validateForm.addControl('address', new FormControl('', []))
        }

        this.validateForm.addControl(item.fieldKey, new FormControl({ value: null, disabled: item.disabled === 'true' }, this.setValidators(item)))
        
        item.dealData = await this.getDealData(item)
      })
    })
    // console.log(this.validateForm)
    // console.log(this.groupList)
  }

  //#region 动态表单处理 | 异步数据获取 
  setValidators(item: any): any[]{
    let validators = []
    if(item.required === 'true'){
      validators.push(Validators.required)
    }
    if(item.validator){
      if(item.validator.type === 'reg'){
        validators.push(Validators.pattern(item.validator.filter))
      }
    }

    return validators
  }
  asyncRequestData(data: any): Observable<any>{
    const method = data.method
    const url = '/' + data.url
    return this.http.get(url)
    // .pipe(map((value: any) => {
    //   console.log(value)
    //   if(value && value.length > 0){
    //     return value.map((item: any) => {
    //       const temp = {} as any
    //       temp.id
    //     })
    //   }
    // }))
  }
  async getDealData(field: any){
    const fieldData = field.fieldData
    const fieldType = field.fieldType
    let data = null
    if(!fieldData) return null

    if(fieldData.type === 'asyncRequest'){
      
      try{
        data = await lastValueFrom(this.asyncRequestData(fieldData.data))
      }catch(err){
        console.log(err)
      }
      
      if(fieldType === 'reactSelect'){
        data = getLeafData(data) // 最后一层添加 isLeaf
      }
    }

    if(fieldData.type === 'data' && fieldType === 'select'){
      data = fieldData.data
    }

    return data
  }
  //#endregion

  //#region 提交
  btnLoading = false
  disableBtn = false
  onSubmit(){
    console.log(this.validateForm)
    // 0. 校验
    if(!this.formValidate()){
      return
    }

    // 1. 提交表单数据
    let data = this.validateForm.getRawValue()
    data = { 
      ...data,  
      setId: this.setId, 
      typeId: this.typeId,
    }

    // 1.1 特殊值处理
    data = dataFormat(data, this)

    // 2. 是否需要用户编号信息
    if(this.usageCodeInfo){
      data = { ...data, ...(this.usageCodeInfo as any) }
    }
    // 3. 是否有银行信息
    // if(this.validateForm.get('accountNum')){
    //   data = { ...data, ...this.bankInfo, bank: this.bankInfo }
    // }
    
    // 4. 特殊业务逻辑处理
    data = beforSubmit(data, this)

    // 5. 同意申请须知
    if(this.needKnowContent && !this._getControl(this.applyAgreeKey)?.value){
      // return this.util.infoAutoClose('办理此业务需同意申请须知！')
    }

    if(this.signKey && !this._getControl(this.signKey)?.value){
      // return this.util.infoAutoClose('请签名！')
    }

    // 6. 提交
    this.btnLoading = true
    this.submit(data).subscribe(res => {
      this.btnLoading = false
      this.submitBtnVisible = false
      this.usageCodeDisabled = true
      this.disableForm()
      this.message.success('提交成功');
    }, error => {
      this.btnLoading = false
      // this.util.createErrorMessage(error)
    })
  }
  submit(data: any): Observable<any>{
    const url = `/api/gsxmcp/cf/mg/v1.0/funcData`
    return this.http.post(url, data)
  }
  onReset(){
    this.message.confirmModal('重置将清空所有字段信息,并返回上一页, 确认重置吗？', () => {
      // this.router.navigate([this.redirect_url])
      history.go(-1)
    })
  }
  doBack(){
    // this.router.navigate([this.redirect_url])
    history.go(-1)
  }
  submitBtnVisible = true
  uploadAvailable = true
  disableForm(){
    this.validateForm.disable()
    this.uploadAvailable = false
  }
  // 表单校验
  formValidate(){
    let controls = this.validateForm.controls;
    for (let i in controls) {
      controls[i].markAsDirty();
      controls[i].updateValueAndValidity();
    }
    
    for(let i in controls){
      if(controls[i].invalid && i !== this.signKey){
        console.log(i, ' =========> ', controls[i])
        return false
      }
    }

    return true
  }
  //#endregion

  //#region 动态表单逻辑 and 事件处理
  needFormatValues: { key: string, value: string }[] = []
  selectChange(value: string, field: any){
    const fieldEvent = field.fieldEvent
    console.log(fieldEvent)
    if(!fieldEvent) return

    // 临时存放 条件(filter)为真 要设置的 字段:属性value
    // 最后一起遍历设置
    let tempEventData = {
      required: [],
      disabled: [],
      visible: [],
      defaultValue: [],
      validator: []
    }

    fieldEvent.forEach((ev: any) => {
      const key = ev.key // 受影响的字段
      const evValue = ev.value  // 要设置 key 的属性的值
      const { filter, type } = ev.fieldValue // 条件 | 条件为真时 设置
      
      if(type === 'logic'){
        let logicRes = false
        if(filter.indexOf('&&') > -1){
          logicRes = this._getFilterIsTrue(filter, '&&')
        }else if(filter.indexOf('||') > -1){
          logicRes = this._getFilterIsTrue(filter, '||')
        }else{
          logicRes = this._getFilterIsTrue(filter, ' ')
        }
        if(logicRes){
          this._setFieldData(evValue, tempEventData, key)
        }
      }
    })
    this._setGroupList(tempEventData)
  }
  reactSelectChange(value: any, field: any){
    if(!value) return
    let tempIndex = this.needFormatValues.findIndex(_ => _.key === field.fieldKey)
    if(tempIndex === -1){
      this.needFormatValues.push({ key: field.fieldKey, value:  value.join() })
    }else{
      this.needFormatValues[tempIndex] = { key: field.fieldKey, value: value.join() }
    }
    // console.log(this._getControl(field.fieldKey).value)
    // this._setValue(field.fieldKey, value[value.length - 1])
  }
  onDateChange(value: any, field: any){
    if(!value) return
    let tempIndex = this.needFormatValues.findIndex(_ => _.key === field.fieldKey)
    if(tempIndex === -1){
      this.needFormatValues.push({ key: field.fieldKey, value: this.dateFormat(value) })
    }else{
      this.needFormatValues[tempIndex] = { key: field.fieldKey, value: this.dateFormat(value) }
    }
    // this._setValue(field.fieldKey, this.dateFormat(value))
  }
  dateFormat(value: any, format = 'yyyy-MM-dd HH:mm:ss'){
    return formatDate(value, format, 'zh-CN')
  }
  
  _getFilterIsTrue(filter: string, separator: string): boolean{
    const filterArr: any[] = filter.split(separator)
    const res: any = []
    filterArr.forEach(x => {
      if(x.indexOf('==') > -1){
        const k = x.split('==')[0].replace('Model.', '')
        const v = x.split('==')[1].replace(/\'/g, '')
        res.push((this.validateForm.get(k)?.value)?.toString() === v)
      }
      if(x.indexOf('!=') > -1){
        const k = x.split('!=')[0].replace('Model.', '')
        const v = x.split('!=')[1].replace(/\'/g, '')
        res.push((this.validateForm.get(k)?.value)?.toString() !== v)
      }
    })

    // TODO 只适合连续且同一种符号
    if(separator === '&&'){
      return res.find((_: any) => _ === false) === undefined
    }
    if(separator === '||'){
      return res.find((_: any) => _ === true) !== undefined
    }
    if(separator === ' '){
      return res[0]
    }
    return false
  }
  /**
   * 1. 收集条件(filter)为真时要设置的字段和属性
   * 2. 通过 validateForm 设置字段 校验 disable/enable defaultValue
   * @param evValue 要设置的属性名和属性值
   * @param temp tempEventData 临时存储当条件(filter)为真时需要设置的属性和对应的字段
   * @param key 需要设置的字段
   */
  _setFieldData(evValue: any, temp: any, key: string){
    Object.keys(evValue).forEach(_ => {
      // 先把数据加到 tempEventData 
      temp[_].push({ key,  value: evValue[_]['data'] })

      if(_ === 'required'){
        if(evValue[_]['data'] === 'true'){
          this._setValidators(key, [Validators.required])
        
          // 特殊处理 accountNum 后期去掉
          if(key === 'accountNum'){
            this.validateForm.get('bankId')?.setValidators([Validators.required])
            this.validateForm.get('account')?.setValidators([Validators.required])
            this.validateForm.get('accountNum')?.clearValidators()
          }
        }else{
          this._clearValidators(key, false)

          // 特殊处理 accountNum 后期去掉
          if(key === 'accountNum'){
            this.validateForm.get('bankId')?.clearValidators()
            this.validateForm.get('account')?.clearValidators()
            this.validateForm.get('accountNum')?.clearValidators()
          }
        }
      }
      if(_ === 'disabled'){
        if(evValue[_]['data'] === 'true'){
          this._disable(key)
        }else{
          this._enable(key)
        }
      }
      if(_ === 'defaultValue'){
        if(key === 'smallArea'){
          this._setValue(key, null)
        }else{
          if(evValue[_]['data'].indexOf('Model') > -1){
            // defaultValue 取 Model 的值
            const modelName = (evValue[_]['data'] as string).substring(6)
            this._setValue(key, this._getControl(modelName)?.value)
          }else{
            this._setValue(key, evValue[_]['data'])
          }
        }
      }
      if(_ === 'visible'){
        if(evValue[_]['data'] === 'true'){
          this._setValidators(key, [ Validators.required ])
        }else{
          this._clearValidators(key)
        }
      }
      if(_ === 'validator'){
        this._setValidators(key, [Validators.required, Validators.pattern(evValue[_]['data']['filter'])])
      }
    })
  }
  /**
   * 设置 groupList 响应表单页面: 可见性visible 红星required ...
   * @param temp tempEventData
   */
  _setGroupList(temp: any){
    Object.keys(temp).forEach(key => {
      this.groupList.forEach((group: any) => {
        let groupData = group.groupData
        groupData.forEach((item: any) => {
          let fieldKey = temp[key].find((_: any) => _.key === item.fieldKey)
          if(fieldKey){
            item[key] = fieldKey['value']
          }
        })
      })
    })
  }
  //#endregion

  // 上传文件
  uploadBack(e: string, fieldKey: string){
    this.validateForm.get(fieldKey)?.setValue(e)
  }

  getLocationInfo(e: any, fieldKey: string){
    console.log(e)
    this._getControl(fieldKey)?.setValue(e)
  }

  //#region 用户编号处理
  usageCodeInfo = null
  async usageCodeChange(e: any){
    // delete e.temp
    this.usageCodeInfo = e
    this.validateForm.get('userNo')?.setValue(e.userNo)
    if(this.validateForm.get('bindType')){
      this.validateForm.get('bindType')?.setValue(e.bindType)
    }

    // 用户编号校验
    const msg = await this.common.usageCodeValid(this.setId, e.usageCode)
    if(msg){
      this.message.error(msg)
      this.disableBtn = true
    }else{
      this.disableBtn = false
    }
  }
  //#endregion

  //#region 开户银行
  bankList: any = [];
  codeNumber = '';
  bankIsLoading = false;
  bankInfo: any = {}
  bankSearch(value: string){
    this.bankIsLoading = true;
    // this.bankTransferService.getBankList(this.codeNumber, value).subscribe(res => {
    //   if(res){
    //     this.bankList = res.resultList;
    //   }else{
    //     this.bankList = [];
    //   }
    //   this.bankIsLoading = false;
    // }, error => {
    //   console.log(error);
    //   this.bankIsLoading = false;
    //   // this.util.createErrorMessage(error);
    // });
  }
  onBankChange(value: string){
    let bank: any = this.bankList.find((item: any) => {
      return item.bankId === value;
    })
    if(bank){
      this.bankInfo = { ...this.bankInfo, bankName: bank.bankName, bankCode: bank.bankCode, bankId: bank.bankId }
      this._setValue('accountNum', JSON.stringify(this.bankInfo))
    }
  }
  accountChange(value: string){
    this.bankInfo['account'] = value
    this._setValue('accountNum', JSON.stringify(this.bankInfo))
  }
  //#endregion

  //#region searchInput
  onInputSearch$ = new Subject<string>()
  onInputSearch(value: string, field: any): void {
    if(!value) {
      field.dealData = []
      return
    }
    const { asyncRequest } = field.fieldCustom // 输入框值变时请求数据
    if(!asyncRequest) return
    
    let { method, url, data: { urlParam } } = asyncRequest
    let params = ''
    if(urlParam && urlParam.length > 0){
      for(let i = 0; i < urlParam.length; i++){
        const { label, required, valueKey } = urlParam[i]
        // TODO value 的值需要判空
        const value = this.validateForm?.get(urlParam[i].value.replace('Model.', ''))?.value
        if(required === 'true' && !value){
          // return this.util.infoAutoClose(`请先输入 ${label}`)
        }
        params = `${params}${valueKey}=${value}&`
      }
    }
    if(params){
      url = '/' + url + '?' + params.substring(0, params.length-1) + `&${field.fieldKey}=${value}`
    }
    
    if(method === 'GET'){
      this.http.get(url).subscribe((data: any) => {
        if(!data) return

        const listOfOption: Array<{ value: string; text: string }> = [];
        data.forEach((item: any) => {
          const value: any = Object.values(item)[0]
          listOfOption.push({
            value: value,
            text: value
          });
        })
        field.dealData = listOfOption
      });
    }
  }
  inputSearchFilter = (input: string, option?: NzOptionComponent) => {
    return option?.nzValue.indexOf(input) > -1
  }
  //#endregion

  //#region 申请须知
  needKnowContent = null
  applyAgreeKey = ''
  applyModalVisible = false
  showApply(){
    console.log(111222)
    if(this.isDetail === 'false') return
    this.applyModalVisible = true
  }
  applyCancel(){
    this._setValue(this.applyAgreeKey, false)
    this.message.error('办理此业务需同意申请须知！')
    this.applyModalVisible = false
  }
  applyAgree(){
    this._setValue(this.applyAgreeKey, true)
    this.applyModalVisible = false
  }
  onAgreeChange(v: string){
    this._setValue(this.applyAgreeKey, v)
    if(!v){
      this.message.error('办理此业务需同意申请须知！')
    }
  }

  //#endregion

  //#region 签名
  signKey = ''
  signModalVisible = false
  showSignModal(){
    this.signModalVisible = true
  }
  onSignChange(signData: object){
    console.log(signData)
  }
  signDataChange(signData: object){
    console.log(signData)
    this._setValue(this.signKey, signData)
  }
  //#endregion
  _getIfApplyOrSign(groupList: any[]){
    console.log('aaaaa')

    let group = groupList.find(item => item.groupName.indexOf('资料上传') > -1)
    if(!group) return
    
    const groupData = group.groupData
    if(!groupData || groupData.length <= 0) return
    
    let apply = groupData.find((_: any) => _.fieldType === 'apply')
    let sign = groupData.find((_: any) => _.fieldType === 'sign')
    
    if(sign){
      this.signKey = sign.fieldKey
    }

    if(apply) {
      this.applyAgreeKey = apply.fieldKey
      // TODO 此处注意防止 undefined
      const url = '/' + apply.fieldData.data.url
      this.dyFormService.getApplyAgree(url).subscribe((res: any) => {
        this.needKnowContent = res[0].needKnowContent
        this.showApply()
      }, error => {
        this.needKnowContent = null
      })
    }
  }

  _getField(typeId: any, isDetail = 'true'): Observable<any>{
    let url = ''
    if(isDetail === 'true'){
      // url = `/api/gsxmcp/cf/mg/v1.0/field/13`
      url = `/api/gsxmcp/cf/mg/v1.0/field/${typeId}`
    }else{
      url = `/api/gsxmcp/cf/mg/v1.0/field/binddata/${typeId}`
    }
    // SWITCH-CODE
    // return this.http.get(url)
    return of(DY_FORM_LINK.find(_ => _.typeId === this.typeId)?.mockData)
  }
  _getBindData(id: any): Observable<any>{
    const url = `/api/gsxmcp/cf/mg/v1.0/field/binddata/${id}`
    return this.http.get(url)
  }

  _getDefaultValue(value: string){
    console.log(value)
    // 缓存的值
    if(value && value.indexOf('session') > -1){
      return this.userInfo[value.replace('session.', '')]
    }

    // Model 取值, validateForm 的字段的值
    if(value && value.indexOf('Model') > -1){
    }
    return value
  }

  //#region 表单 control 操作
  _getControl(key: string): AbstractControl | null{
    return this.validateForm.get(key) || null
  }
  /**
   * 表单字段赋值
   * @param key 字段名
   * @param value 字段值
   */
  _setValue(key: string, value: any){
    if(this._getControl(key)){
      this._getControl(key)?.setValue(value)
    }
  }
  _setValidators(key: string, validators: any){
    if(this.getMineValidator(key)){
      validators.push(this.getMineValidator(key))
    }

    if(this._getControl(key)){
      this._getControl(key)?.setValidators(validators)
    }
  }
  // 本身是否配置正则表达式
  getMineValidator(key: string){
    let mineValidator = null
    for(let i = 0; i < this.groupList.length; i++){
      const groupData = (this.groupList[i] as any).groupData
      if(!groupData){
        continue
      }
      const fieldData = groupData.find((_: any) => _.fieldKey === key)
      if(fieldData && fieldData.validator) {
        if(fieldData.validator.type === 'reg'){
          mineValidator = Validators.pattern(fieldData.validator.filter)
        }        
      }
    }
    
    return mineValidator
  }
  _clearValidators(key: string, visible = true){
    if(this._getControl(key)){
      this._getControl(key)?.clearValidators()
    }

    if(this.getMineValidator(key) && !visible){
      if(this._getControl(key)){
        this._getControl(key)?.setValidators([(this.getMineValidator(key) as ValidatorFn)])
      }
    }
  }
  _disable(key: any){
    if(this._getControl(key)){
      this._getControl(key)?.disable()
    }
  }
  _enable(key: any){
    if(this._getControl(key)){
      this._getControl(key)?.enable()
    }
  }
  //#endregion

}
